﻿// -----------------------------------------------------------------------
// <copyright file="StreamWriter.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;
using System.Text;
using Company.IO.Interfaces;

namespace Company.System.IO
{
    /// <summary>
    /// Implements a TextWriter for writing characters to a stream in a particular encoding.
    /// </summary>
    [Guid("8404e736-73ae-4f12-819f-b181af63d6fb")]
    public class StreamWriter : IStreamWriter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="StreamWriter"/> class.
        /// </summary>
        /// <param name="systemIoConverter">The system io converter.</param>
        /// <param name="streamWriter">The stream writer.</param>
        public StreamWriter(ISystemIoConverter systemIoConverter, global::System.IO.StreamWriter streamWriter)
        {
            SystemConverter = systemIoConverter;
            InternalStreamWriter = streamWriter;
        }

        #region Implementation of IStreamWriter

        /// <summary>
        /// Get or Sets the converter
        /// </summary>
        private ISystemIoConverter SystemConverter { get; set; }

        /// <summary>
        /// Get or Sets the internal stream object
        /// </summary>
        private global::System.IO.StreamWriter InternalStreamWriter { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the StreamWriter will flush its buffer to the underlying stream after every call to StreamWriter.Write.
        /// </summary>
        bool IStreamWriter.AutoFlush
        {
            get { return InternalStreamWriter.AutoFlush; }
            set { InternalStreamWriter.AutoFlush = value; }
        }

        /// <summary>
        /// Gets the underlying stream that interfaces with a backing store.
        /// </summary>
        IStream IStreamWriter.BaseStream
        {
            get { return Convert(InternalStreamWriter.BaseStream); }
        }

        /// <summary>
        /// Gets the Encoding in which the output is written.
        /// </summary>
        Encoding IStreamWriter.Encoding
        {
            get { return InternalStreamWriter.Encoding; }
        }

        /// <summary>
        /// Closes the current StreamWriter object and the underlying stream.
        /// </summary>
        /// <exception cref="EncoderFallbackException">
        /// The current encoding does not support displaying half of a Unicode surrogate pair.
        /// </exception>
        void IStreamWriter.Close()
        {
            InternalStreamWriter.Close();
        }

        /// <summary>
        /// Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        /// The current writer is closed.
        /// </exception>
        /// <exception cref="IIOException">
        /// An I/O error has occurred.
        /// </exception>
        /// <exception cref="EncoderFallbackException">
        /// The current encoding does not support displaying half of a Unicode surrogate pair.
        /// </exception>
        void IStreamWriter.Flush()
        {
            InternalStreamWriter.Flush();
        }

        /// <summary>
        /// Writes a character to the stream.
        /// </summary>
        /// <param name="value">The character to write to the text stream.</param>
        /// <exception cref="ObjectDisposedException">
        /// AutoFlush is true or the StreamWriter buffer is full, and current writer is closed.
        /// </exception>
        /// <exception cref="IIOException">
        /// An I/O error has occurred.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// AutoFlush is true or the StreamWriter buffer is full, 
        /// and the contents of the buffer cannot be written to the 
        /// underlying fixed size stream because the StreamWriter is at the end the stream.
        /// </exception>
        void IStreamWriter.Write(char value)
        {
            InternalStreamWriter.Write(value);
        }

        /// <summary>
        /// Writes a character array to the stream.
        /// </summary>
        /// <param name="buffer">A character array containing the data to write. If buffer is a null reference (Nothing in Visual Basic), nothing is written.</param>
        /// <exception cref="ObjectDisposedException">
        /// AutoFlush is true or the StreamWriter buffer is full, and current writer is closed.
        /// </exception>
        /// <exception cref="IIOException">
        /// An I/O error has occurred.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// AutoFlush is true or the StreamWriter buffer is full, 
        /// and the contents of the buffer cannot be written to the 
        /// underlying fixed size stream because the StreamWriter is at the end the stream.
        /// </exception>
        void IStreamWriter.Write(char[] buffer)
        {
            InternalStreamWriter.Write(buffer);
        }

        /// <summary>
        /// Writes a subarray of characters to the stream.
        /// </summary>
        /// <param name="buffer">A character array containing the data to write.</param>
        /// <param name="index">The index into buffer at which to begin writing.</param>
        /// <param name="count">The number of characters to read from buffer.</param>
        /// <exception cref="ArgumentException">
        /// The buffer length minus index is less than count.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// buffer is a null reference (Nothing in Visual Basic). 
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// index or count is negative.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        /// AutoFlush is true or the StreamWriter buffer is full, and current writer is closed.
        /// </exception>
        /// <exception cref="IIOException">
        /// An I/O error has occurred.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// AutoFlush is true or the StreamWriter buffer is full, 
        /// and the contents of the buffer cannot be written to the 
        /// underlying fixed size stream because the StreamWriter is at the end the stream.
        /// </exception>
        void IStreamWriter.Write(char[] buffer, int index, int count)
        {
            InternalStreamWriter.Write(buffer, index, count);
        }

        /// <summary>
        /// Writes a string to the stream.
        /// </summary>
        /// <param name="value">The string to write to the stream. If value is null, nothing is written.</param>
        /// <exception cref="ObjectDisposedException">
        /// AutoFlush is true or the StreamWriter buffer is full, and current writer is closed.
        /// </exception>
        /// <exception cref="IIOException">
        /// An I/O error has occurred.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// AutoFlush is true or the StreamWriter buffer is full, 
        /// and the contents of the buffer cannot be written to the 
        /// underlying fixed size stream because the StreamWriter is at the end the stream.
        /// </exception>
        void IStreamWriter.Write(string value)
        {
            InternalStreamWriter.Write(value);
        }

        #endregion

        /// <summary>
        /// Converts the specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns>The converted object</returns>
        private IStream Convert(global::System.IO.Stream stream)
        {
            return SystemConverter.Convert(stream);
        }
    }
}